package com.scientific.research.gobang.service.match.impl;


import com.scientific.research.gobang.mapper.MatchMapper;
import com.scientific.research.gobang.mapper.SignMessageMapper;
import com.scientific.research.gobang.pojo.MatchMessage;
import com.scientific.research.gobang.pojo.SignMessage;
import com.scientific.research.gobang.service.MatchCodeRunService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

@Service("matchCodeRunServiceImpl")
@Scope("prototype")
public class MatchCodeRunServiceImpl extends CodeAndCodeServiceImpl implements MatchCodeRunService {
    private MatchMessage match;
    private List<SignMessage> signMessageList;
    private String result = "";

    @Autowired
    private MatchMapper matchMapper;
    @Autowired
    private SignMessageMapper signMessageMapper;

    //调用这个方法执行一场比赛。此方法调用淘汰赛方法KnockOut，KnockOut调用KnockOutOnce
    @SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
    @Override
    public void RunOneMatch(int matchId) {
        RunCodeServiceImpl.matchCodeServiceInit(matchId);
        this.match = matchMapper.selectById(matchId);

        HashMap<String, Object> selectMatchId = new HashMap<>();
        selectMatchId.put("match_id", matchId);
        this.signMessageList = signMessageMapper.selectByMap(selectMatchId);
        if ("淘汰赛".equals(this.match.getType())) {//目前只支持淘汰赛，后续增加其它比赛
            KnockOut();
        }
    }

    @SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
    @Override
    public void KnockOut()//淘汰赛方法
    {
        int length, winnerNowLength;
        int rounds = 1;//第几轮比赛
        boolean isEndJudge = true;
        int[] winner = new int[signMessageList.size()];
        for (length = 0; length < winner.length; length++) {
            winner[length] = length;
        }
        winnerNowLength = signMessageList.size();

        while (isEndJudge) {//每一次while循环都会让rounds++代表进行第几轮比赛，每一轮都会有很多场比赛
            this.result += "第" + rounds + "轮\n";
            int lengthTwo = 0;
            if (winnerNowLength % 2 == 1 && winnerNowLength != 1) {
                Random random = new Random();
                int soonInt = random.nextInt(winnerNowLength - 1);
                this.result += "第1场" + signMessageList.get(winner[soonInt]).getUserEmail() + "vs" + signMessageList.get(winner[winnerNowLength - 1]).getUserEmail() + "\n";
                winner[0] = KnockOutOnce(winner[soonInt], winner[winnerNowLength - 1]);
                result += "finalWinner:" + signMessageList.get(winner[0]).getUserEmail() + "\n";
                lengthTwo = 1;
            }
            for (length = 0; length + 1 < winnerNowLength; length += 2) {
                this.result += "第" + (lengthTwo + 1) + "场" + signMessageList.get(winner[length]).getUserEmail() + "VS" + signMessageList.get(winner[length + 1]).getUserEmail() + "\n";
                winner[lengthTwo] = KnockOutOnce(winner[length], winner[length + 1]);
                result += "finalWinner:" + signMessageList.get(winner[lengthTwo]).getUserEmail() + "\n";
                lengthTwo += 1;
            }
            winnerNowLength = lengthTwo;
            rounds += 1;
            if (winnerNowLength == 0) {
                isEndJudge = false;
            }
        }
        result += "$$thisMatchWinner$$" + signMessageList.get(winner[0]).getUserEmail();
        MatchMessage saveMatch = new MatchMessage();
        saveMatch.setId(this.match.getId());
        saveMatch.setCodeResult(result);
        saveMatch.setResult("已完成");
        this.matchMapper.updateById(saveMatch);
    }

    @SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
    @Override
    public int KnockOutOnce(int userOne, int userTwo)//执行一次淘汰赛方法
    {
        SignMessage playOne = signMessageList.get(userOne);
        SignMessage playTwo = signMessageList.get(userTwo);
        Map runResult = CodeAndCodeOnce(playOne.getUserEmail(), playOne.getLanguage(), playOne.getCode(), playTwo.getUserEmail(), playTwo.getLanguage(), playTwo.getCode());
        this.result += runResult.get("result");
        if ("userOne".equals(runResult.get("winner"))) {
            return userOne;
        } else {
            return userTwo;
        }
    }
}
